/***************************chromiumupdater.cpp*************************/
/*****************************************************************************/
/*******************Browsers Daily Build Updater************************/
/************Copyright (C) 2010-2011  Gianluigi Biancucci*************/
/*****************************************************************************/
/*****This is free software, and you are welcome to redistribute it****/
/*****and / or modify underthe terms of GPLV2 License.**************/
/*****This program comes with ABSOLUTELY NO WARRANTY*****/
/*****************************************************************************/

#include "ChromiumUpdater.h"
#include "singletondownloader.h"
#include "iostream"
#include "QFile"
#include <QMessageBox>
#include <QIcon>
#include <QLabel>
#include <QDir>
#include <QProcess>
#include <QStringList>
#include "chromiumupdater.h"
#include <QVariant>
#include "paths.h"
#include <QDir>
#include "winfunc.h"
#include "OSDaB-Zip\unzip.h"
#include "QStringList"
#include "QProcess"

ChromiumUpdater::ChromiumUpdater(QString arch, QString installPath)

{


    downloader = SingletonDownloader::getInstance();
    QDir dir;
    dir = QDir();
    if(!dir.exists(CHROSETPATH+"/"))dir.mkdir(CHROSETPATH+"/");
    _32="win32";
    currPath.setPath(installPath);
    this->setArch(arch);
    BName = "Chromium";
    lastError ="No Error";
}




void ChromiumUpdater::setArch(QString arch){
    //Forced to 32 bit version because there are no 64 bit version of Chromium.(For further use)
    currOsType=_32;

}

bool ChromiumUpdater::getLatestVersion(QString * lastVer){
    // Design choice: Update chromium version, only when a new trunk version is realeased.
    // This is because the choromium bot build a new svn with no evident changes every hour.
    // The trunk version is updated instead about one time per day. I think is enought :)
    //
    // Updated trunk version message to catch: <msg>Updating trunk VERSION from 608.0 to 609.0</msg>

    QByteArray  res;
    if(downloader->syncGet("http://build.chromium.org/f/chromium/snapshots/chromium-rel-xp/LATEST",&res)){
        QString latestVer(res);

     int i =0;
     while(i!=1){
         QByteArray changeLogBA;

         downloader->syncGet("http://build.chromium.org/f/chromium/snapshots/chromium-rel-xp/"+latestVer+"/changelog.xml",&changeLogBA);
         QString changelog(changeLogBA);
         QString ver = this->getContentBetween(changelog,"<msg>Updating trunk VERSION from ","</msg>");
         if(!ver.isEmpty()){
                ver.remove(0,ver.lastIndexOf(" ")+1);
                ver.remove(ver.indexOf("."),ver.length());
             *lastVer=ver;
                qDebug(lastVer->toStdString().c_str());
             return true;
         }else{
             //Checks in every folder to find the latest updated trunk version message.
             QVariant v =latestVer;
             int c = v.toInt();
             c--;
             QVariant p = c;
             latestVer=p.toString();
         }
        }
        return true;
    }
    else{
        lastError ="Undefined error when checking the latest version of Chromium.\nCheck your connection settings and try again.";
        return false;
    }

}

bool ChromiumUpdater::getInstalledVersion(QString * installedVer){
    // Checks the version of chrome.dll library with GetFileVersion() System call.
    // Unfortunately, the installation with the zip ad installer.exe put this file in 2 different folders.
    // One in the most external Folder, and one in an internal one.
    // So we had to check if there are 2 or more chrome.dll files and get the version of the newest
    // which should be the currently used.
    float versNumExt=0;
    float versNum=0;

    QDir currTempPath;
    currTempPath.setPath(currPath.path());
    if(currTempPath.exists("chrome.dll")){
        WORD a,b,c,d;
        QString dllPathExt=currTempPath.path()+"/chrome.dll";
        GetAppVersion(dllPathExt.toStdWString().c_str(),&a,&b,&c,&d);
        QVariant g=c;
        QVariant p = g.toString();
        versNumExt =p.toFloat();
    }
    QString basePath=currTempPath.path();
    //Reverse the directory list to take as first entry the newest chrome.dll file.
    QStringList dirs=currTempPath.entryList(QDir::Dirs|QDir::NoDotAndDotDot,QDir::Name|QDir::DirsFirst|QDir::Reversed);
    for(int i =0;i<dirs.length();i++){
        currTempPath.setPath(basePath+"/"+dirs.at(i));
        if(currTempPath.exists("chrome.dll")){
            QString dllPath=currTempPath.path()+"/chrome.dll";
            WORD a,b,c,d;
            GetAppVersion(dllPath.toStdWString().c_str(),&a,&b,&c,&d);
            QVariant g=c;
            QVariant p = g.toString();
            versNum=p.toFloat();
            i=dirs.length()+1;
        }

    }

    if(versNum==0 && versNumExt == 0){
        lastError="Cannot detect chromium version. Maybe corrupted installation or wrong path. Check settings.";
        return false;
    }

    float finalVer;
    if(versNumExt >= versNum){
        finalVer= versNumExt;
    }else finalVer = versNum;

    QVariant versStr = finalVer;
    qDebug(versStr.toString().toStdString().c_str());
    if(!versStr.toString().isEmpty()){*installedVer=versStr.toString();

        return true;}
    else{
        lastError="Cannot retrieve correct Chromium version. Sorry.";
        return false;
    }


}

bool ChromiumUpdater::downloadLatest(QString * exePath){
    QByteArray  res;
    if(!downloader->syncGet("http://build.chromium.org/f/chromium/snapshots/chromium-rel-xp/LATEST",&res)) {
        lastError ="Undefined error when downloading Chromium.\nCheck your connection settings and try again.";
        return false;
    }
    QString version(res);

    QByteArray chromium;
    if( downloader->syncGet("http://build.chromium.org/f/chromium/snapshots/chromium-rel-xp/"+version+"/chrome-win32.zip",&chromium)){
        QFile* chrfile = new QFile(CHROSETPATH+"/chromium_"+currOsType+"_"+version+".zip");
        chrfile->open(QIODevice::WriteOnly);
        chrfile->write(chromium);
        chrfile->close();
        delete chrfile;
        *exePath= CHROSETPATH+"/chromium_"+currOsType+"_"+version+".zip";
        return true;
    } else {
        lastError ="Undefined error when downloading Chromium.\nCheck your connection settings and try again.";
        return false;
    }
}

bool ChromiumUpdater::install(QString zipPath){

    UnZip uz;

    //Open Zip file
    UnZip::ErrorCode ec = uz.openArchive(zipPath);
    if (ec != UnZip::Ok) {
        lastError="Cannot open Chromium archive.\nTry manual installation.";
        return false;
    }

    //Extract zip file in temporary path
    ec =      uz.extractAll(CHROSETPATH+"/temp/");
    if (ec != UnZip::Ok) {
        lastError="Cannot extract Chromium.\nTry manual installation.";
        return false;
    }

    //close zip file
    uz.closeArchive();

    //delete current chromium install folder for a new fresh install (user data obviously ramains)
   /* QString delCmd = "rmdir \""+currPath.path()+"/\"";
    delCmd.replace("/","\\");
    delCmd+=" /S /Q";
    qDebug(delCmd.toStdString().c_str());
    system(delCmd.toStdString().c_str());*/

    //copy the new chromium version in the install path
    QString copyCmd = "xcopy "+CHROSETPATH+"/temp/chrome-win32/* \""+currPath.path()+"\"";
    copyCmd.replace("/","\\");
    copyCmd+=" /E /H /I /K /Y";
    qDebug(copyCmd.toStdString().c_str());
    system(copyCmd.toStdString().c_str());

    //delete the temporary zip file path
   QString delCmd = "rmdir "+CHROSETPATH+"/temp";
    delCmd.replace("/","\\");
    delCmd+=" /S /Q";
    qDebug(delCmd.toStdString().c_str());
    system(delCmd.toStdString().c_str());

    QMessageBox msg;
    msg.setWindowTitle("Update Ok");
    msg.setIcon(QMessageBox::Information);
    msg.setText("Chromium succesfully updated.\n("+currPath.path()+")");
    msg.exec();

    return true;
}

bool ChromiumUpdater::checkInstallPath(){
    if(currPath.exists("chrome.exe"))return true;
    else return false;
}

QString ChromiumUpdater::getBrowserName(){

    return BName;

}

QString ChromiumUpdater::getLastError(){

    return lastError;

}

QString ChromiumUpdater::getContentBetween(QString source, QString startStr, QString endStr){
    int start = source.indexOf(startStr);
    if(start != -1){
        source.remove(0,start+startStr.length());
        int end = source.indexOf(endStr);
        if (end != -1){
            source.remove(end,source.length()-end);
            return source;
        }else return "";

    }else return "";
    }
